In [1]:
# Importing dependencies:
import cv2
import glob
import time
import pickle
import random
import collections
import numpy as np
from collections import deque
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
from skimage.feature import hog
from skimage import color, exposure
from sklearn.svm import LinearSVC
from scipy.ndimage.measurements import label
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from moviepy.editor import VideoFileClip
from IPython.display import HTML
%matplotlib inline

print('Imported all dependencies!')
Imported all dependencies!
In [2]:
# Creating the variables where the images will be saved:
highway_test_images = glob.glob('test_images/*.jpg')
highway_vehicles_images = glob.glob('test_images/vehicles/**/*.png')
highway_non_vehicles_images = glob.glob('test_images/non-vehicles/**/*.png')
highway_all_images = glob.glob('test_images/**/**/*.png')
highway_test_image1 = mpimg.imread('test_images/test1.jpg')

for images in highway_test_images:
    
    # Reading the images:
    highway_images = mpimg.imread(images)
    
    # Formatting the amount of columns and the size of the images that will be displayed:
    f, ax = plt.subplots(1, 1, figsize=(12, 9), sharey=True)
    f.tight_layout()
    
    # Original images:  
    plt.imshow(highway_images)
    plt.subplots_adjust(left=0., right=1, top=0.9, bottom=0.)

print('Variables created!')
print('Number of vehicle images:', len(highway_vehicles_images))
print('Number of non-vehicles images:', len(highway_non_vehicles_images))
print('Total number of images:', len(highway_all_images))
Variables created!
Number of vehicle images: 8792
Number of non-vehicles images: 8968
Total number of images: 17760
In [3]:
# Saving images into arrays:
cars = []
notcars = []

# Appending the car and notcar images into their appropiate arrays:
for image in highway_vehicles_images:
    cars.append(image)
    
for image in highway_non_vehicles_images:
    notcars.append(image)
        
print(len(cars))
print(len(notcars))
print('Images saved into arrays!')
8792
8968
Images saved into arrays!
In [4]:
# Setting parameters:
color_space = 'YCrCb' # Can be RGB, HSV, LUV, HLS, YUV, YCrCb
orient = 9  # HOG orientations
pix_per_cell = 8 # HOG pixels per cell
cell_per_block = 2 # HOG cells per block
hog_channel = 'ALL' # Can be 0, 1, 2, or "ALL"
spatial_size = (32, 32) # Spatial binning dimensions
hist_bins = 32    # Number of histogram bins
spatial_feat = True # Spatial features on or off
hist_feat = True # Histogram features on or off
hog_feat = True # HOG features on or off
y_start_stop = [400, 650] # Min and max in y to search in slide_window()
scale = 1.5

print('Parameters set!')
Parameters set!
In [5]:
# Creating get_hog function (extracted from Udacity lesson):
def get_hog_features(img, orient, pix_per_cell, cell_per_block, vis=False, feature_vec=True):
    
    # Call with two outputs if vis==True
    if vis == True:
        features, hog_image = hog(img, orientations=orient, 
                                  pixels_per_cell=(pix_per_cell, pix_per_cell),
                                  cells_per_block=(cell_per_block, cell_per_block), 
                                  transform_sqrt=True, 
                                  visualise=vis, feature_vector=feature_vec)
        return features, hog_image
    # Otherwise call with one output
    else:      
        features = hog(img, orientations=orient, 
                       pixels_per_cell=(pix_per_cell, pix_per_cell),
                       cells_per_block=(cell_per_block, cell_per_block), 
                       transform_sqrt=True, 
                       visualise=vis, feature_vector=feature_vec)
        return features
    
print('Function is ready to use!')
Function is ready to use!
In [6]:
# Visualizing the pictures:
# Generate a random index to look at a car image:
car_ind = np.random.randint(0, len(cars))
notcar_ind = np.random.randint(0, len(notcars))

# Read in the image:
image = mpimg.imread(cars[car_ind])
gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)

# Implementing the get_hog_features in a random image selected from the array:
features, hog_image = get_hog_features(gray, orient=orient, pix_per_cell=pix_per_cell, 
                                       cell_per_block=cell_per_block, vis=True, feature_vec=False)

# Formatting the amount of columns and the size of the images that will be displayed:
f, ax = plt.subplots(1, 2, figsize=(24, 9))
f.tight_layout()

# Example Car Image:  
ax[0].imshow(image, cmap='gray')
ax[0].set_title('Example Car Image:', fontsize=40)
plt.subplots_adjust(left=0., right=1, top=0.9, bottom=0.)
plt.imsave('output_images/example_image.jpg', image)

# HOG Visualization:
ax[1].imshow(hog_image)
ax[1].set_title('HOG Visualization:', fontsize=40)
plt.subplots_adjust(left=0., right=1, top=0.9, bottom=0.)
plt.imsave('output_images/hog_image.jpg', hog_image)

print('Image saved in directory!')
Image saved in directory!
In [7]:
# Creating the bin_spatial function (extracted from Udacity lesson):
def bin_spatial(img, size=(32, 32)):
    color1 = cv2.resize(img[:,:,0], size).ravel()
    color2 = cv2.resize(img[:,:,1], size).ravel()
    color3 = cv2.resize(img[:,:,2], size).ravel()
    return np.hstack((color1, color2, color3))

print('Function ready to use!')
Function ready to use!
In [8]:
# Creating the color_hist function (extracted from Udacity lesson):
def color_hist(img, nbins=32):
    
    # Computing the histogram of the color channels separately:
    channel1_hist = np.histogram(img[:,:,0], bins=nbins)
    channel2_hist = np.histogram(img[:,:,1], bins=nbins)
    channel3_hist = np.histogram(img[:,:,2], bins=nbins)
    
    # Concatenating the histograms into a single feature vector:
    hist_features = np.concatenate((channel1_hist[0], channel2_hist[0], channel3_hist[0]))
    
    # Returning the individual histograms, bin_centers and feature vector:
    return hist_features

print('Function ready to use!')
Function ready to use!
In [9]:
# Creating the extract_features function (extracted from Udacity lesson):
def extract_features(imgs, color_space='YCrCb', spatial_size=(32, 32), hist_bins=32, orient=9, pix_per_cell=8, 
                     cell_per_block=2, hog_channel='ALL', spatial_feat=True, hist_feat=True, hog_feat=True):
    
    # Creating a list to append feature vectors:
    features = []
    
    # Iterating through the list of images:
    for file in imgs:
        file_features = []
        
        # Reading in each one by one:
        image = mpimg.imread(file)
        
        # Applying color conversion if other than 'RGB':
        if color_space != 'RGB':
            if color_space == 'HSV':
                feature_image = cv2.cvtColor(image, cv2.COLOR_RGB2HSV)
            elif color_space == 'LUV':
                feature_image = cv2.cvtColor(image, cv2.COLOR_RGB2LUV)
            elif color_space == 'HLS':
                feature_image = cv2.cvtColor(image, cv2.COLOR_RGB2HLS)
            elif color_space == 'YUV':
                feature_image = cv2.cvtColor(image, cv2.COLOR_RGB2YUV)
            elif color_space == 'YCrCb':
                feature_image = cv2.cvtColor(image, cv2.COLOR_RGB2YCrCb)
        else: feature_image = np.copy(image)      
            
        # Implementing bin_spatial function if spatial_feat is true:
        if spatial_feat == True:
            spatial_features = bin_spatial(feature_image, size=spatial_size)
            file_features.append(spatial_features)  
           
        # Implementing hist_feat function if hist_feat is true:
        if hist_feat == True:
            hist_features = color_hist(feature_image, nbins=hist_bins)
            file_features.append(hist_features)
            
        # Implementing get_hog_features if hog_faet is true:
        if hog_feat == True:
            
            # Calling get_hog_features() with vis=False, feature_vec=True
            if hog_channel == 'ALL':
                hog_features = []
                for channel in range(feature_image.shape[2]):
                    hog_features.append(get_hog_features(feature_image[:,:,channel], 
                                        orient, pix_per_cell, cell_per_block, 
                                        vis=False, feature_vec=True))
                hog_features = np.ravel(hog_features)        
            else:
                hog_features = get_hog_features(feature_image[:,:,hog_channel], orient, 
                            pix_per_cell, cell_per_block, vis=False, feature_vec=True)
                
            # Appending the new feature vector to the features list:
            file_features.append(hog_features)
        features.append(np.concatenate(file_features))
        
    # Returning list of feature vectors:
    return features

print('Function ready to use!')
Function ready to use!
In [10]:
# Creating the slide_window function (extracted from Udacity lesson):
def slide_window(img, x_start_stop=[None, None], y_start_stop=[None, None], xy_window=(64, 64), 
                 xy_overlap=(0.5, 0.5)):
    
    # If x and/or y start/stop positions are not defined, set to image size:
    if x_start_stop[0] == None:
        x_start_stop[0] = 0
    if x_start_stop[1] == None:
        x_start_stop[1] = img.shape[1]
    if y_start_stop[0] == None:
        y_start_stop[0] = 0
    if y_start_stop[1] == None:
        y_start_stop[1] = img.shape[0]
        
    # Computing the span of the region to be searched:
    xspan = x_start_stop[1] - x_start_stop[0]
    yspan = y_start_stop[1] - y_start_stop[0]
    
    # Computing the number of pixels per step in x/y:
    nx_pix_per_step = np.int(xy_window[0]*(1 - xy_overlap[0]))
    ny_pix_per_step = np.int(xy_window[1]*(1 - xy_overlap[1]))
    
    # Computing the number of windows in x/y:
    nx_buffer = np.int(xy_window[0]*(xy_overlap[0]))
    ny_buffer = np.int(xy_window[1]*(xy_overlap[1]))
    nx_windows = np.int((xspan-nx_buffer)/nx_pix_per_step) 
    ny_windows = np.int((yspan-ny_buffer)/ny_pix_per_step) 
    
    # Initializing a list to append window positions to:
    window_list = []
    
    # Looping through finding x and y window positions:
    for ys in range(ny_windows):
        for xs in range(nx_windows):
            
            # Calculating window position:
            startx = xs*nx_pix_per_step + x_start_stop[0]
            endx = startx + xy_window[0]
            starty = ys*ny_pix_per_step + y_start_stop[0]
            endy = starty + xy_window[1]
            
            # Appending window position to list:
            if starty > 400 and endy <= 650:
                window_list.append(((startx, starty), (endx, endy)))
                
    # Returning the list of windows
    return window_list

print('Function ready to use!')
Function ready to use!
In [11]:
# Creating the draw_boxes function (extracted from Udacity lesson):
def draw_boxes(img, bboxes, color=(0, 0, 255), thick=6):
    
    # Making a copy of the image:
    imcopy = np.copy(img)
    
    # Iterating through the bounding boxes:
    for bbox in bboxes:
        
        # Drawing a rectangle given bbox coordinates:
        cv2.rectangle(imcopy, bbox[0], bbox[1], color, thick)
        
    # Returning the image copy with boxes drawn
    return imcopy

print('Function ready to use!')
Function ready to use!
In [14]:
# Visualizing the image:
# Formatting the amount of columns and the size of the images that will be displayed:
f, ax = plt.subplots(1, 2, figsize=(24, 9))
f.tight_layout()

# Example Car Image:  
ax[0].imshow(highway_test_image1)
ax[0].set_title('Example Car Image:', fontsize=40)
plt.subplots_adjust(left=0., right=1, top=0.9, bottom=0.)

slide_window_image = slide_window(highway_test_image1, x_start_stop=[None, None], y_start_stop=[400, 650], 
                                  xy_window=(64, 64), xy_overlap=(0.5, 0.5))
draw_boxes_image = draw_boxes(highway_test_image1, slide_window_image)

# DBoxes Drawn:
ax[1].imshow(draw_boxes_image)
ax[1].set_title('Boxes Drawn Window:', fontsize=40)
plt.subplots_adjust(left=0., right=1, top=0.9, bottom=0.)
plt.imsave('output_images/draw_boxes_image.jpg', draw_boxes_image)

print('Image saved in directory!')
Image saved in directory!
In [15]:
# Creating the single_img_features function (extracted from Udacity lesson):
def single_img_features(img, color_space='YCrCb', spatial_size=(32, 32), hist_bins=32, orient=9, 
                        pix_per_cell=8, cell_per_block=2, hog_channel='ALL',spatial_feat=True, 
                        hist_feat=True, hog_feat=True):  
    
    # Defining an empty list to receive features:
    img_features = []
    
    # Applying color conversion if other than 'RGB':
    if color_space != 'RGB':
        if color_space == 'HSV':
            feature_image = cv2.cvtColor(img, cv2.COLOR_RGB2HSV)
        elif color_space == 'LUV':
            feature_image = cv2.cvtColor(img, cv2.COLOR_RGB2LUV)
        elif color_space == 'HLS':
            feature_image = cv2.cvtColor(img, cv2.COLOR_RGB2HLS)
        elif color_space == 'YUV':
            feature_image = cv2.cvtColor(img, cv2.COLOR_RGB2YUV)
        elif color_space == 'YCrCb':
            feature_image = cv2.cvtColor(img, cv2.COLOR_RGB2YCrCb)
    else: feature_image = np.copy(img)      
        
    # Computing spatial features if flag is set:
    if spatial_feat == True:
        spatial_features = bin_spatial(feature_image, size=spatial_size)
        img_features.append(spatial_features)
        
    # Computing histogram features if flag is set:
    if hist_feat == True:
        hist_features = color_hist(feature_image, nbins=hist_bins)
        img_features.append(hist_features)
        
    # Computing HOG features if flag is set:
    if hog_feat == True:
        if hog_channel == 'ALL':
            hog_features = []
            for channel in range(feature_image.shape[2]):
                hog_features.extend(get_hog_features(feature_image[:, :, channel], orient, pix_per_cell, 
                                                     cell_per_block, vis=False, feature_vec=True))      
        else:
            hog_features = get_hog_features(feature_image[:, :, hog_channel], orient, pix_per_cell, 
                                            cell_per_block, vis=False, feature_vec=True)
        # Appending features to list:
        img_features.append(hog_features)

    # Returning concatenated array of features:
    return np.concatenate(img_features)

print('Function ready to use!')
Function ready to use!
In [16]:
# Creating the search_window function (extracted from Udacity lesson):
def search_windows(img, windows, clf, scaler, color_space='YCrCb', spatial_size=(32, 32), hist_bins=32, 
                   hist_range=(0, 256), orient=9, pix_per_cell=8, cell_per_block=2, hog_channel='ALL', 
                   spatial_feat=True, hist_feat=True, hog_feat=True):

    # Creating an empty list to receive positive detection windows:
    on_windows = []
    
    # Iterating over all windows in the list:
    for window in windows:
        
        # Extracting the test window from original image:
        test_img = cv2.resize(img[window[0][1]:window[1][1], window[0][0]:window[1][0]], (64, 64))
        
        # Extracting features for that window using single_img_features():
        features = single_img_features(test_img, color_space=color_space, spatial_size=spatial_size, 
                                       hist_bins=hist_bins, orient=orient, pix_per_cell=pix_per_cell, 
                                       cell_per_block=cell_per_block, hog_channel=hog_channel, 
                                       spatial_feat=spatial_feat, hist_feat=hist_feat, hog_feat=hog_feat)
        
        # Scaling extracted features to be fed to classifier:
        test_features = scaler.transform(np.array(features).reshape(1, -1))
        
        # Predicting using your classifier:
        prediction = clf.predict(test_features)
        
        # If positive (prediction == 1) then save the window:
        if prediction == 1:
            on_windows.append(window)
            
    # Returning windows for positive detections
    return on_windows

print('Function ready to use!')
Function ready to use!
In [17]:
# Reducing the sample size to speed the training time:
sample_size = 2000
cars = cars[0:sample_size]
notcars = notcars[0:sample_size]

print(len(cars))
print(len(notcars))
print('Arrays modified!')
2000
2000
Arrays modified!
In [18]:
# Extracting the features of the images and training the dataset (extracted from Udacity lesson):
car_features = extract_features(cars, color_space=color_space, spatial_size=spatial_size, hist_bins=hist_bins, 
                                orient=orient, pix_per_cell=pix_per_cell, cell_per_block=cell_per_block, 
                                hog_channel=hog_channel, spatial_feat=spatial_feat, hist_feat=hist_feat, 
                                hog_feat=hog_feat)

notcar_features = extract_features(notcars, color_space=color_space, spatial_size=spatial_size, 
                                   hist_bins=hist_bins, orient=orient, pix_per_cell=pix_per_cell, 
                                   cell_per_block=cell_per_block, hog_channel=hog_channel, 
                                   spatial_feat=spatial_feat, hist_feat=hist_feat, hog_feat=hog_feat)

# Creating X variable and stacking both cars and notcars images and transforming them to float64:
X = np.vstack((car_features, notcar_features)).astype(np.float64)

# Fitting a per-column scaler:
X_scaler = StandardScaler().fit(X)

# Applying the scaler to X:
scaled_X = X_scaler.transform(X)

# Defining the labels vector:
y = np.hstack((np.ones(len(car_features)), np.zeros(len(notcar_features))))

# Splitting up data into randomized training and test sets:
rand_state = np.random.randint(0, 100)
X_train, X_test, y_train, y_test = train_test_split(scaled_X, y, test_size=0.2, random_state=rand_state)

print('Using:', orient, 'orientations', pix_per_cell, 'pixels per cell and', cell_per_block,'cells per block')
print('Feature vector length:', len(X_train[0]))

# Using a linear SVC:
svc = LinearSVC()

# Checking the training time for the SVC:
t=time.time()
svc.fit(X_train, y_train)
t2 = time.time()
print(round(t2-t, 2), 'Seconds to train SVC...')

# Checking the score of the SVC:
print('Test Accuracy of SVC = ', round(svc.score(X_test, y_test), 4))

# Checking the prediction time for a single sample:
t=time.time()
n_predict = 10
print('My SVC predicts: ', svc.predict(X_test[0:n_predict]))
print('For these', n_predict, 'labels: ', y_test[0:n_predict])
t2 = time.time()
print(round(t2-t, 5), 'Seconds to predict', n_predict, 'labels with SVC')
Using: 9 orientations 8 pixels per cell and 2 cells per block
Feature vector length: 8460
1.97 Seconds to train SVC...
Test Accuracy of SVC =  0.9938
My SVC predicts:  [ 0.  1.  1.  0.  0.  0.  1.  0.  0.  1.]
For these 10 labels:  [ 0.  1.  1.  0.  0.  0.  1.  0.  0.  1.]
0.00181 Seconds to predict 10 labels with SVC
In [19]:
# Visualizing the image:
# Formatting the amount of columns and the size of the images that will be displayed:
f, ax = plt.subplots(1, 2, figsize=(24, 9))
f.tight_layout()

# Example Car Image:  
ax[0].imshow(highway_test_image1)
ax[0].set_title('Example Car Image:', fontsize=40)
plt.subplots_adjust(left=0., right=1, top=0.9, bottom=0.)

# Making a copy of the images:
draw_image = np.copy(highway_test_image1)

# Setting the images to a value of 0.0 to 1.0:
image = highway_test_image1.astype(np.float32)/255

# Implementing the slide_window function:
windows = slide_window(image, x_start_stop=[None, None], y_start_stop=[400, 656], xy_window=(64, 64), 
                       xy_overlap=(0.5, 0.5))

# Implementing the search_window function:
hot_windows = search_windows(image, windows, svc, X_scaler, color_space=color_space, 
                             spatial_size=spatial_size, hist_bins=hist_bins, orient=orient, 
                             pix_per_cell=pix_per_cell, cell_per_block=cell_per_block, 
                             hog_channel=hog_channel, spatial_feat=spatial_feat, hist_feat=hist_feat, 
                             hog_feat=hog_feat)                       

# Implementing the draw_boxes function:
extracted_image = draw_boxes(draw_image, hot_windows, color=(0, 0, 255), thick=6)  

# DBoxes Drawn:
ax[1].imshow(extracted_image)
ax[1].set_title('Extracted Cars:', fontsize=40)
plt.subplots_adjust(left=0., right=1, top=0.9, bottom=0.)
plt.imsave('output_images/extracted_image.jpg', extracted_image)

print('Image saved in directory!')
Image saved in directory!
In [20]:
# Visualizing the images:
for images in highway_test_images:
    
    # Reading the images:
    image = mpimg.imread(images)
    
    # Making a copy of the images:
    draw_image = np.copy(image)
    
    # Setting the images to a value of 0.0 to 1.0:
    image = image.astype(np.float32)/255
    
    # Implementing the slide_window function:
    windows = slide_window(image, x_start_stop=[None, None], y_start_stop=[400, 656], xy_window=(64, 64), 
                           xy_overlap=(0.5, 0.5))

    # Implementing the search_window function:
    hot_windows = search_windows(image, windows, svc, X_scaler, color_space=color_space, 
                                 spatial_size=spatial_size, hist_bins=hist_bins, orient=orient, 
                                 pix_per_cell=pix_per_cell, cell_per_block=cell_per_block, 
                                 hog_channel=hog_channel, spatial_feat=spatial_feat, hist_feat=hist_feat, 
                                 hog_feat=hog_feat)                       

    # Implementing the draw_boxes function:
    window_img = draw_boxes(draw_image, hot_windows, color=(0, 0, 255), thick=6)  
    
    # Formatting the amount of columns and the size of the images that will be displayed:
    f, ax = plt.subplots(1, 2, figsize=(24, 9))
    f.tight_layout()
    
    # Original images:  
    ax[0].imshow(image)
    ax[0].set_title('Original Image:', fontsize=40)
    plt.subplots_adjust(left=0., right=1, top=0.9, bottom=0.)
    
    # Birds's Eye View of images:
    ax[1].imshow(window_img)
    ax[1].set_title('False Positives Image:', fontsize=40)
    plt.subplots_adjust(left=0., right=1, top=0.9, bottom=0.)
In [21]:
# Creating the convert_color function (extracted from Udacity lesson):
def convert_color(img, conv='RGB2YCrCb'):
    
    if conv == 'RGB2YCrCb':
        return cv2.cvtColor(img, cv2.COLOR_RGB2YCrCb)
    if conv == 'BGR2YCrCb':
        return cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb)
    if conv == 'RGB2LUV':
        return cv2.cvtColor(img, cv2.COLOR_RGB2LUV)
    if conv == 'RGB2YUV':
        return cv2.cvtColor(img, cv2.COLOR_RGB2YUV)
    
print('Function ready to use!')
Function ready to use!
In [22]:
# Creating the find_cars function (extracted from Udacity lesson):
def find_cars(img, ystart, ystop, scale, svc, X_scaler, orient, pix_per_cell, cell_per_block, spatial_size, 
              hist_bins):
    
    # Creating an empty array to save the boxes:
    bbox_list = []
    
    # Maing a copy of the images:
    draw_img = np.copy(img)
    
    # Setting the images to a value of 0.0 to 1.0:
    img = img.astype(np.float32)/255
    
    img_tosearch = img[ystart:ystop,:,:]
    ctrans_tosearch = convert_color(img_tosearch, conv='RGB2YCrCb')
    if scale != 1:
        imshape = ctrans_tosearch.shape
        ctrans_tosearch = cv2.resize(ctrans_tosearch, (np.int(imshape[1]/scale), np.int(imshape[0]/scale)))
        
    ch1 = ctrans_tosearch[:,:,0]
    ch2 = ctrans_tosearch[:,:,1]
    ch3 = ctrans_tosearch[:,:,2]

    # Defining blocks and steps as above:
    nxblocks = (ch1.shape[1] // pix_per_cell) - cell_per_block + 1
    nyblocks = (ch1.shape[0] // pix_per_cell) - cell_per_block + 1 
    nfeat_per_block = orient*cell_per_block**2
    
    # 64 was the orginal sampling rate, with 8 cells and 8 pix per cell
    window = 64
    nblocks_per_window = (window // pix_per_cell) - cell_per_block + 1
    cells_per_step = 2  # Instead of overlap, define how many cells to step
    nxsteps = (nxblocks - nblocks_per_window) // cells_per_step
    nysteps = (nyblocks - nblocks_per_window) // cells_per_step
    
    # Computing individual channel HOG features for the entire image:
    hog1 = get_hog_features(ch1, orient, pix_per_cell, cell_per_block, feature_vec=False)
    hog2 = get_hog_features(ch2, orient, pix_per_cell, cell_per_block, feature_vec=False)
    hog3 = get_hog_features(ch3, orient, pix_per_cell, cell_per_block, feature_vec=False)
    
    for xb in range(nxsteps):
        for yb in range(nysteps):
            ypos = yb*cells_per_step
            xpos = xb*cells_per_step
            
            # Extracting HOG for this patch:
            hog_feat1 = hog1[ypos:ypos+nblocks_per_window, xpos:xpos+nblocks_per_window].ravel() 
            hog_feat2 = hog2[ypos:ypos+nblocks_per_window, xpos:xpos+nblocks_per_window].ravel() 
            hog_feat3 = hog3[ypos:ypos+nblocks_per_window, xpos:xpos+nblocks_per_window].ravel() 
            hog_features = np.hstack((hog_feat1, hog_feat2, hog_feat3))

            xleft = xpos*pix_per_cell
            ytop = ypos*pix_per_cell

            # Extracting the image patch:
            subimg = cv2.resize(ctrans_tosearch[ytop:ytop+window, xleft:xleft+window], (64,64))
          
            # Getting color features:
            spatial_features = bin_spatial(subimg, size=spatial_size)
            hist_features = color_hist(subimg, nbins=hist_bins)

            # Scaling features and make a prediction:
            test_features = X_scaler.transform(np.hstack((spatial_features, hist_features, 
                                                          hog_features)).reshape(1, -1))    
            #test_features = X_scaler.transform(np.hstack((shape_feat, hist_feat)).reshape(1, -1))    
            test_prediction = svc.predict(test_features)
            
            if test_prediction == 1:
                xbox_left = np.int(xleft * scale)
                ytop_draw = np.int(ytop * scale)
                win_draw = np.int(window * scale)
                cv2.rectangle(draw_img, (xbox_left, ytop_draw + ystart), 
                              (xbox_left + win_draw, ytop_draw + win_draw + ystart), (0,0,255),6) 
                bbox_list.append(((xbox_left, ytop_draw + ystart), 
                                  (xbox_left + win_draw, ytop_draw + win_draw + ystart)))
                
    return draw_img, bbox_list

print('Function ready to use!')
Function ready to use!
In [23]:
# Visualizing the image:
ystart = 400
ystop = 656

# Formatting the amount of columns and the size of the images that will be displayed:
f, ax = plt.subplots(1, 2, figsize=(24, 9))
f.tight_layout()

# Example Car Image:  
ax[0].imshow(highway_test_image1)
ax[0].set_title('Example Car Image:', fontsize=40)
plt.subplots_adjust(left=0., right=1, top=0.9, bottom=0.)

find_car_image, bbox_list = find_cars(highway_test_image1, ystart, ystop, scale, svc, X_scaler, orient, 
                                      pix_per_cell, cell_per_block, spatial_size, hist_bins)

# Find Car Visualization:
ax[1].imshow(find_car_image)
ax[1].set_title('Find Car Image:', fontsize=40)
plt.subplots_adjust(left=0., right=1, top=0.9, bottom=0.)
plt.imsave('output_images/find_car_image.jpg', find_car_image)

print('Image saved in directory!')
Image saved in directory!
In [24]:
# Creating the add_heat function:
def add_heat(heatmap, bbox_list):
    
    # Iterating through list of bboxes:
    for box in bbox_list:
        
        # Adding += 1 for all pixels inside each bbox:
        heatmap[box[0][1]:box[1][1], box[0][0]:box[1][0]] += 1

    # Returning updated heatmap:
    return heatmap

print('Function ready to use!')
Function ready to use!
In [25]:
# Creating the apply_threshold function:
def apply_threshold(heatmap, threshold):
    
    # Zering out pixels below the threshold:
    heatmap[heatmap <= threshold] = 0
    
    # Returning thresholded map:
    return heatmap

print('Function ready to use!')
Function ready to use!
In [26]:
# Creating the draw_labeled_bboxes:
def draw_labeled_bboxes(img, labels):
    
    # Iterating through all detected cars:
    for car_number in range(1, labels[1]+1):
        
        # Finding pixels with each car_number label value:
        nonzero = (labels[0] == car_number).nonzero()
        
        # Identifying x and y values of those pixels:
        nonzeroy = np.array(nonzero[0])
        nonzerox = np.array(nonzero[1])
        
        # Defining a bounding box based on min/max x and y:
        bbox = ((np.min(nonzerox), np.min(nonzeroy)), (np.max(nonzerox), np.max(nonzeroy)))
        
        # Drawing the box on the image:
        cv2.rectangle(img, bbox[0], bbox[1], (0, 0, 255), 6)
        
    return img

print('Function ready to use!')
Function ready to use!
In [27]:
# Creating the draw function:
def draw(image, bbox_list):
    
    # Creating black image:
    heat = np.zeros_like(image[:, :, 0]).astype(np.float)

    # Adding heat to each box in box list:
    heat = add_heat(heat, bbox_list)

    # Applying threshold to help remove false positives:
    heat = apply_threshold(heat, 1)
    
    # Visualizing the heatmap when displaying:
    heatmap = np.clip(heat, 0, 255)

    # Finding final boxes from heatmap using label function:
    labels = label(heatmap)
    draw_img = draw_labeled_bboxes(np.copy(image), labels)
    
    return draw_img, heatmap

print('Function ready to use!')
Function ready to use!
In [28]:
# Visualizing the image:
# Formatting the amount of columns and the size of the images that will be displayed:
f, ax = plt.subplots(1, 2, figsize=(24, 9))
f.tight_layout()

draw_img, heatmap = draw(highway_test_image1, bbox_list)

# Example Car Image:  
ax[0].imshow(draw_img)
ax[0].set_title('Example Car Image:', fontsize=40)
plt.subplots_adjust(left=0., right=1, top=0.9, bottom=0.)

# Heatmap Visualization:
ax[1].imshow(heatmap)
ax[1].set_title('Heatmap Image:', fontsize=40)
plt.subplots_adjust(left=0., right=1, top=0.9, bottom=0.)
plt.imsave('output_images/heatmap_image.jpg', heatmap)

print('Image saved in directory!')
Image saved in directory!
In [29]:
# Creating pipeline to process the images:
heatmap_saved = deque(maxlen = 15)

def pipeline(image):
    
    bboxes = []
    ystart = 400
    ystop = 500 
    out_img, bboxes1 = find_cars(image, ystart, ystop, 1.0, svc, X_scaler, orient, pix_per_cell, 
                                 cell_per_block, spatial_size, hist_bins)
    
    ystart = 400
    ystop = 500 
    out_img, bboxes2 = find_cars(image, ystart, ystop, 1.3, svc, X_scaler, orient, pix_per_cell, 
                                 cell_per_block, spatial_size, hist_bins)
    
    ystart = 410
    ystop = 500 
    out_img, bboxes3 = find_cars(out_img, ystart, ystop, 1.4, svc, X_scaler, orient, pix_per_cell, 
                                 cell_per_block, spatial_size, hist_bins)
    
    ystart = 420
    ystop = 556 
    out_img, bboxes4 = find_cars(out_img, ystart, ystop, 1.6, svc, X_scaler, orient, pix_per_cell, 
                                 cell_per_block, spatial_size, hist_bins)
    
    ystart = 430
    ystop = 556 
    out_img, bboxes5 = find_cars (out_img, ystart, ystop, 1.8, svc, X_scaler, orient, pix_per_cell, 
                                  cell_per_block, spatial_size, hist_bins)
    
    ystart = 430
    ystop = 556 
    out_img, bboxes6 = find_cars (out_img, ystart, ystop, 2.0, svc, X_scaler, orient, pix_per_cell, 
                                  cell_per_block, spatial_size, hist_bins)
    
    ystart = 440
    ystop = 556 
    out_img, bboxes7 = find_cars (out_img, ystart, ystop, 1.9, svc, X_scaler, orient, pix_per_cell, 
                                  cell_per_block, spatial_size, hist_bins)
    
    ystart = 400
    ystop = 556 
    out_img, bboxes8 = find_cars (out_img, ystart, ystop, 1.3, svc, X_scaler, orient, pix_per_cell, 
                                  cell_per_block, spatial_size, hist_bins)
    
    ystart = 400
    ystop = 556 
    out_img, bboxes9 = find_cars (out_img, ystart, ystop, 2.2, svc, X_scaler, orient, pix_per_cell, 
                                  cell_per_block, spatial_size, hist_bins)
    
    ystart = 500 
    ystop = 656 
    out_img, bboxes10 = find_cars (out_img, ystart, ystop, 3.0, svc, X_scaler, orient, pix_per_cell, 
                                   cell_per_block, spatial_size, hist_bins)
    
    bboxes.extend(bboxes1)
    bboxes.extend(bboxes2)
    bboxes.extend(bboxes3)
    bboxes.extend(bboxes4)
    bboxes.extend(bboxes5)
    bboxes.extend(bboxes6)
    bboxes.extend(bboxes7)
    bboxes.extend(bboxes8)
    bboxes.extend(bboxes9)
    bboxes.extend(bboxes10)
    
    # Creating black image:
    heat = np.zeros_like(out_img[:,:,0]).astype(np.float)

    # Adding heat to each box in box list:
    heat = add_heat(heat, bboxes)

    # Applying threshold to help remove false positives:
    heat = apply_threshold(heat, 2)
    
    # Visualizing the heatmap when displaying:
    heatmap = np.clip(heat, 0, 255)
    heatmap_saved.append(heatmap)
    
    # Iterating through the heat boxes found and saving the in the array:
    for heat in heatmap_saved:
        heatmap = heatmap + heat

    # Finding final boxes from heatmap using label function:
    labels = label(heatmap)
    draw_img = draw_labeled_bboxes(np.copy(image), labels)
    
    return draw_img

print('Function ready to use!')    
Function ready to use!
In [30]:
# Visualizing the images:
for images in highway_test_images:
    
    image = mpimg.imread(images)
    
    # Formatting the amount of columns and the size of the images that will be displayed:
    f, ax = plt.subplots(1, 2, figsize=(24, 9))
    f.tight_layout()
    
    # Original images:  
    ax[0].imshow(image)
    ax[0].set_title('Original Image:', fontsize=40)
    plt.subplots_adjust(left=0., right=1, top=0.9, bottom=0.)
    
    # Pipeline Images:
    highway_pipeline = pipeline(image)
    ax[1].imshow(highway_pipeline)
    ax[1].set_title('Pipeline View:', fontsize=40)
    plt.subplots_adjust(left=0., right=1, top=0.9, bottom=0.)
In [31]:
# Saving the video file in a variable:
highway_video = 'project_video.mp4'
clip = VideoFileClip('project_video.mp4')
img_size = (1280, 720)

# Showing the video:
HTML("""
<video width="920" height="620" controls>
  <source src="{0}">
</video>
""".format(highway_video))
Out[31]:
In [32]:
# Finding lanes in project video:
test_video = 'output_video/test_video.mp4'
clip1 = VideoFileClip("test_video.mp4")

write_clip = clip1.fl_image(pipeline)
%time write_clip.write_videofile(test_video, audio=False)

# Showing the video:
HTML("""
<video width="920" height="620" controls>
  <source src="{0}">
</video>
""".format(test_video))
[MoviePy] >>>> Building video output_video/test_video.mp4
[MoviePy] Writing video output_video/test_video.mp4
 97%|█████████▋| 38/39 [00:51<00:01,  1.36s/it]
[MoviePy] Done.
[MoviePy] >>>> Video ready: output_video/test_video.mp4 

CPU times: user 48.4 s, sys: 2.12 s, total: 50.6 s
Wall time: 53.4 s
Out[32]:
In [33]:
# Finding lanes in project video:
project_lane_video = 'output_video/project_lane_video.mp4'
clip1 = VideoFileClip("project_video.mp4")

write_clip = clip1.fl_image(pipeline)
%time write_clip.write_videofile(project_lane_video, audio=False)

# Showing the video:
HTML("""
<video width="920" height="620" controls>
  <source src="{0}">
</video>
""".format(project_lane_video))
[MoviePy] >>>> Building video output_video/project_lane_video.mp4
[MoviePy] Writing video output_video/project_lane_video.mp4
100%|█████████▉| 1260/1261 [28:38<00:01,  1.36s/it]
[MoviePy] Done.
[MoviePy] >>>> Video ready: output_video/project_lane_video.mp4 

CPU times: user 27min 24s, sys: 1min 9s, total: 28min 34s
Wall time: 28min 40s
Out[33]: